package im.zego.CustomerVideoCapture;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import com.texeljoy.ht_effect.HTPanelLayout;
import im.zego.commontools.logtools.AppLogger;
import im.zego.commontools.logtools.LogView;
import im.zego.commontools.logtools.logLinearLayout;
import im.zego.customvideorendering.R;
import im.zego.keycenter.KeyCenter;
import im.zego.zegoexpress.ZegoExpressEngine;
import im.zego.zegoexpress.callback.IZegoApiCalledEventHandler;
import im.zego.zegoexpress.callback.IZegoEventHandler;
import im.zego.zegoexpress.constants.ZegoPublishChannel;
import im.zego.zegoexpress.constants.ZegoPublisherState;
import im.zego.zegoexpress.constants.ZegoRoomState;
import im.zego.zegoexpress.constants.ZegoScenario;
import im.zego.zegoexpress.constants.ZegoVideoBufferType;
import im.zego.zegoexpress.entity.ZegoCustomVideoCaptureConfig;
import im.zego.zegoexpress.entity.ZegoEngineProfile;
import im.zego.zegoexpress.entity.ZegoUser;
import org.json.JSONObject;

public class CustomerVideoCaptureActivity extends AppCompatActivity {

  ZegoExpressEngine engine;
  long appID;
  String appSign;
  String userID;
  String roomID;
  String publishStreamID;
  ZegoUser user;
  ZegoCustomVideoCaptureConfig captureConfig = new ZegoCustomVideoCaptureConfig();

  TextView roomIDText;
  TextView userIDText;
  Button startPublishButton;
  TextureView preview;
  EditText editPublishStreamID;
  Spinner bufferTypeSpinner;
  RelativeLayout relativeLayout;
  TextView roomState;

  // To store whether the user is publishing the stream
  boolean isPublish = false;
  // To store whether the data source is camera.
  boolean isCamera = true;
  ZegoVideoCaptureCallback videoCapture = null;

  // Unicode of Emoji
  int checkEmoji = 0x2705;
  int crossEmoji = 0x274c;
  int roomConnectedEmoji = 0x1F7E2;
  int roomDisconnectedEmoji = 0x1F534;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_customer_video_capture);
    //todo --- hteffect start
    addContentView(new HTPanelLayout(this).init(getSupportFragmentManager()),
        new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT));
    //todo --- hteffect end


    requestPermission();
    bindView();
    getAppSignAndID();
    setDefaultValue();
    initEngineAndUser();
    setEventHandler();
    setStartPublishButtonEvent();
    setLogComponent();
    setApiCalledResult();
  }

  public void requestPermission() {
    String[] PERMISSIONS_STORAGE = {
        "android.permission.CAMERA",
        "android.permission.RECORD_AUDIO" };

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
      if (ContextCompat.checkSelfPermission(this, "android.permission.CAMERA") != PackageManager.PERMISSION_GRANTED
          || ContextCompat.checkSelfPermission(this, "android.permission.RECORD_AUDIO") != PackageManager.PERMISSION_GRANTED) {
        requestPermissions(PERMISSIONS_STORAGE, 101);
      }
    }
  }

  public void bindView() {
    roomIDText = findViewById(R.id.roomID);
    userIDText = findViewById(R.id.userID);
    startPublishButton = findViewById(R.id.publishButton);
    preview = findViewById(R.id.PreviewView);
    editPublishStreamID = findViewById(R.id.editStreamID);
    relativeLayout = findViewById(R.id.relative_view);
    roomState = findViewById(R.id.roomState);
  }

  public void getAppSignAndID() {
    appSign = KeyCenter.appSign();
    appID = KeyCenter.appID();
  }

  public void setDefaultValue() {
    //set default publish StreamID
    publishStreamID = "0014";
    //set default user ID
    userID = "Android_" + Build.MODEL.replaceAll(" ", "_");
    roomID = "0014";

    // set UI
    userIDText.setText(userID);

    captureConfig.bufferType = ZegoVideoBufferType.GL_TEXTURE_2D;
    setTitle(getString(R.string.custom_video_capture));
  }

  public void initEngineAndUser() {
    // Initialize ZegoExpressEngine
    ZegoEngineProfile profile = new ZegoEngineProfile();
    profile.appID = appID;
    profile.appSign = appSign;
    profile.scenario = ZegoScenario.GENERAL;
    profile.application = getApplication();
    engine = ZegoExpressEngine.createEngine(profile, null);

    AppLogger.getInstance().callApi("Create ZegoExpressEngine");
    //create the user
    user = new ZegoUser(userID);
  }

  public void setStartPublishButtonEvent() {
    startPublishButton.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        publishStreamID = editPublishStreamID.getText().toString();
        //if the user is publishing the stream, this button is used to stop publishing. Otherwise, this button is used to start publishing.
        if (isPublish) {
          stopPublish();
          AppLogger.getInstance().callApi("Stop Publishing Stream:%s", publishStreamID);
        } else {
          startPublish();
          startPublishButton.setText(getString(R.string.stop_publishing));
          AppLogger.getInstance().callApi("Start Publishing Stream:%s", publishStreamID);
        }
      }
    });
  }





  public void startPublish() {
    videoCapture = null;
    engine.enableCustomVideoCapture(true, captureConfig, ZegoPublishChannel.MAIN);

    //todo --- hteffect start ---
    videoCapture = new VideoCaptureFromCamera2(engine);
    videoCapture.setView(preview);
    //todo --- hteffect start ---

    engine.setCustomVideoCaptureHandler(videoCapture);
    engine.loginRoom(roomID, new ZegoUser(userID));
    AppLogger.getInstance().callApi("LoginRoom: %s", roomID);
    engine.startPublishingStream(publishStreamID);
    isPublish = true;
  }

  public void stopPublish() {
    startPublishButton.setText(getString(R.string.start_publishing));
    engine.stopPreview();
    engine.stopPublishingStream();
    engine.logoutRoom(roomID);
    AppLogger.getInstance().callApi("LogoutRoom: %s", roomID);
    engine.enableCustomVideoCapture(false, captureConfig, ZegoPublishChannel.MAIN);
    relativeLayout.removeView(preview);
    relativeLayout.addView(preview);
    isPublish = false;
  }

  public static void actionStart(Activity activity) {
    Intent intent = new Intent(activity, CustomerVideoCaptureActivity.class);
    activity.startActivity(intent);
  }

  @Override
  protected void onDestroy() {
    ZegoExpressEngine.destroyEngine(null);
    super.onDestroy();
  }

  public void setEventHandler() {
    engine.setEventHandler(new IZegoEventHandler() {

      // The callback triggered when the room connection state changes.
      @Override
      public void onRoomStateUpdate(String roomID, ZegoRoomState state, int errorCode, JSONObject extendedData) {
        super.onRoomStateUpdate(roomID, state, errorCode, extendedData);
        // Update room state
        if (state.equals(ZegoRoomState.CONNECTED)) {
          roomState.setText(getEmojiStringByUnicode(roomConnectedEmoji));
        } else if (state.equals(ZegoRoomState.DISCONNECTED)) {
          roomState.setText(getEmojiStringByUnicode(roomDisconnectedEmoji));
        }
      }

      // The callback triggered when the state of stream publishing changes.
      @Override
      public void onPublisherStateUpdate(String streamID, ZegoPublisherState state, int errorCode, JSONObject extendedData) {
        super.onPublisherStateUpdate(streamID, state, errorCode, extendedData);
        if (errorCode != 0 && state.equals(ZegoPublisherState.NO_PUBLISH)) {
          if (isPublish) {
            startPublishButton.setText(getEmojiStringByUnicode(crossEmoji) + getString(R.string.stop_publishing));
          }
        } else {
          if (isPublish) {
            startPublishButton.setText(getEmojiStringByUnicode(checkEmoji) + getString(R.string.stop_publishing));
          }
        }
      }
    });
  }

  public void setApiCalledResult() {
    // Update log with api called results
    ZegoExpressEngine.setApiCalledCallback(new IZegoApiCalledEventHandler() {
      @Override
      public void onApiCalledResult(int errorCode, String funcName, String info) {
        super.onApiCalledResult(errorCode, funcName, info);
        if (errorCode == 0) {
          AppLogger.getInstance().success("[%s]:%s", funcName, info);
        } else {
          AppLogger.getInstance().fail("[%d]%s:%s", errorCode, funcName, info);
        }
      }
    });
  }

  private String getEmojiStringByUnicode(int unicode) {
    return new String(Character.toChars(unicode));
  }

  // Set log component. It includes a pop-up dialog.
  public void setLogComponent() {
    logLinearLayout logHiddenView = findViewById(R.id.logView);
    logHiddenView.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        LogView logview = new LogView(getApplicationContext());
        logview.show(getSupportFragmentManager(), null);
      }
    });
  }
}